function OpenPageAction(id, label) {
	this.id = id;
	this.label = label;
}

OpenPageAction.prototype.close = function() {
}

function OpenDataAction(entityView, scope) {
	OpenDataAction._super.call(this, "openData", "Open Data...");
	this.entityView = entityView;
	this.scope = scope;
}
Object.extend("OpenDataAction", "OpenPageAction");

OpenDataAction.prototype.perform = function() {
	var url = BasePath.get() + "/livcos.org/web/data" + this.entityView.entity.objId + ".html";
	if (this.scope)
		url += "?scope=" + this.scope;
	if (null != this.entityView.entity.id)
		url += "#" + this.entityView.entity.id;
	window.open(url);
}

function OpenObjectAction(entityView, scope) {
	OpenObjectAction._super.call(this, "openObject", "Open Object...");
	this.entityView = entityView;
	this.scope = scope;
}
Object.extend("OpenObjectAction", "OpenPageAction");

OpenObjectAction.prototype.perform = function() {
	var url = BasePath.get() + this.entityView.entity.getId();
	if (this.scope)
		url += "." + this.scope;
	window.open(url);
}

function NavLinkAction(entityView) {
	this.id = "navLink";
	this.label = "Navigate";
	this.entityView = entityView;
}

NavLinkAction.prototype.perform = function() {
	window.location.href = this.entityView.dom.element.href;
}

NavLinkAction.prototype.close = function() {
}

function ShowEditAction(entityView) {
	this.id = "showEdit";
	this.label = "Edit...";
	this.entityView = entityView;
}

ShowEditAction.prototype.perform = function() {
	Doc().editorPanel.open();
}

function ShowEditorAction(entityView, editorKey, editorAction) {
	this.id = "showEditor";
	this.label = editorAction.label;
	this.entityView = entityView;
	this.editorKey = editorKey;
	this.editorAction = editorAction;
}

ShowEditorAction.prototype.perform = function() {
	Doc().editorPanel.open(this.editorKey, this.editorAction);
}

function ShowInsertAction(entity) {
	this.id = "showInsert";
	this.label = "Insert...";
	this.entity = entity;
}

ShowInsertAction.prototype.perform = function() {
	Doc().templatePanel.open();
}

function SelectParentAction(entity) {
	this.id = "selectParent";
	this.label = "Select Parent";
	this.entity = entity;
}

SelectParentAction.prototype.perform = function() {
	var slSp = Doc().selectionSupport;
	if (slSp.current)
		slSp.select(slSp.current.entityView.getParent());
}

function EditAction(id, label, entityView, jobUri) {
	this.id = id;
	this.label = label;
	this.entityView = entityView;
	this.job = jobUri;
	if (!this.job)
		this.job = EDIT_BASE_PATH + EDIT_JOB_URL;
	this.reset();
}

EditAction.prototype.reset = function() {
	this.state = "initial";
}

EditAction.prototype.createJob = function() {
	return new EditJob(this.job, this.doc.doc.statusDisplay, this.doc.contentPanel);
}

EditAction.prototype.perform = function() {
	this.doc = Doc(this.entityView.dom);
	this.doc.lock();
	this.state = "running";
	this.setEntityViewId = this.prepareReselect();
	var editJob = this.createJob();
	this.addData(editJob);
	editJob.executeAction(this);
}

EditAction.prototype.close = function(responseDom) {
	this.doc.unlock();
	if (this.setEntityViewId) {
		var dom = Dom(this.setEntityViewId);
		if (dom)
			this.reselect(dom.getEntityView(), responseDom);
	}
	this.state = "closed";
}

EditAction.prototype.prepareReselect = function() {
	return this.entityView.dom.element.id;
}

EditAction.prototype.reselect = function(ev) {
	this.doc.selectionSupport.select(ev);
}

EditAction.prototype.addData = function(editJob) {
	editJob.addEntityIdData(this.entityView.entity);
}

function InsertAction(entityView, tmpl, suppressEditor) {
	InsertAction._super.call(this, "insert", "Insert", entityView);
	this.tmpl = tmpl;
	this.suppressEditor = suppressEditor;
}
Object.extend("InsertAction", "EditAction");

InsertAction.prototype.addData = function(editJob) {
	editJob.addEntityIdData(this.entityView.entity);
	if (this.tmpl.objId) {
		editJob.addData("tmplObjId", this.tmpl.objId);
		editJob.addData("tmplId", this.tmpl.id);
		for (var i = 0; i < this.tmpl.args.length; i++)
			editJob.addData("tmplArg" + (i + 1), this.tmpl.args[i]);
	}
	else {
		var separatorPos = this.tmpl.indexOf("#");
		editJob.addData("tmplObjId", this.tmpl.substring(0, separatorPos));
		editJob.addData("tmplId", this.tmpl.substring(separatorPos + 1, this.tmpl.length));
	}
	if ((typeof this.into != "undefined") && !this.into)
		editJob.addData("into", "0");
	if (this.path) {
		editJob.addData("path", this.path);
		for (var i = 0; i < this.namespaces.length; ++i) {
			var ns = this.namespaces[i];
			editJob.addData("ns-" + ns.getAttribute("prefix"), ns.getAttribute("uri"));
		}
	}
}

InsertAction.prototype.reselect = function(ev, responseDom) {
	ev = ev.getLastChild();
	if (responseDom) {
		var ins = responseDom.getElementsByTagName("insert")[0];
		if (ins) {
			var id = ins.getAttribute("ref");
			if (ins.nextSibling) {
				var upd = ins.nextSibling.getAttribute("element");
				if (upd)
					id = upd;
			}
			var objId = ins.parentNode.getAttribute("obj");
			var evNew = EntityView.getFirstEntityViewById(null, objId, id);
			if (evNew)
				ev = evNew;
		}
	}
	this.doc.selectionSupport.select(ev);
	if (!this.suppressEditor)
		this.doc.editorPanel.open();
}

function UpdateAction(id, label, entityView, jobUri, form) {
	UpdateAction._super.call(this, id, label, entityView, jobUri);
	this.form = form;
}
Object.extend("UpdateAction", "EditAction");

UpdateAction.prototype.addData = function(editJob) {
	editJob.addFormData(this.form);
}

UpdateAction.prototype.perform = function() {
	UpdateAction._super.prototype.perform.call(this);
	this.doc.editorPanel.close();
}

function UpdateValueAction(entityView, value, path) {
	UpdateValueAction._super.call(this, "update", "Update", entityView);
	this.value = value;
	this.path = path;
}
Object.extend("UpdateValueAction", "EditAction");

UpdateValueAction.prototype.addData = function(editJob) {
	editJob.addEntityIdData(this.entityView.entity);
	editJob.addData("scope", "content");
	editJob.addData("path", this.path);
	editJob.addData("content", this.value);
}

function CloneAction(entityView) {
	CloneAction._super.call(this, "clone", "Clone", entityView);
}
Object.extend("CloneAction", "EditAction");

CloneAction.prototype.reselect = function(ev, responseDom) {
	ev = ev.getNextSibling();
	if (responseDom) {
		var ins = responseDom.getElementsByTagName("insert")[0];
		if (ins) {
			var id = ins.getAttribute("ref");
			var objId = ins.parentNode.getAttribute("obj");
			var evNew = EntityView.getFirstEntityViewById(null, objId, id);
			if (evNew)
				ev = evNew;
		}
	}
	this.doc.selectionSupport.select(ev);
	this.doc.editorPanel.open();
}

function AddRelatedAction(entityView) {
	AddRelatedAction._super.call(this, "addRelated", "Add Related", entityView);
}
Object.extend("AddRelatedAction", "EditAction");

function CreateAction(entityView) {
	CreateAction._super.call(this, "create", "Create Sibling", entityView);
}
Object.extend("CreateAction", "EditAction");

CreateAction.prototype.reselect = function(ev, responseDom) {
	ev = ev.getNextSibling();
	if (responseDom) {
		var ins = responseDom.getElementsByTagName("insert")[0];
		if (ins) {
			var id = ins.getAttribute("ref");
			var objId = ins.parentNode.getAttribute("obj");
			var evNew = EntityView.getFirstEntityViewById(null, objId, id);
			if (evNew)
				ev = evNew;
		}
	}
	this.doc.selectionSupport.select(ev);
	this.doc.editorPanel.open();
}


function DeleteAction(entityView) {
	DeleteAction._super.call(this, "delete", "Delete", entityView, DeleteAction.jobUri);
}
Object.extend("DeleteAction", "EditAction");

DeleteAction.prototype.prepareReselect = function() {
	var sel = this.entityView.getNextSibling();
	if (!sel)
		sel = this.entityView.getPreviousSibling();
	if (sel && this.entityView.id.match("\\.[0-9]*$"))
		sel = this.entityView;
	if (!sel)
		sel = this.entityView.getParent();
	return (sel)?sel.dom.element.id:null;
}


function SnapshotAction(entityView, form) {
	SnapshotAction._super.call(this, "snapshot", "Snapshot", entityView, EDIT_BASE_PATH
			+ EDIT_SNAPSHOT_URL, form);
}
Object.extend("SnapshotAction", "UpdateAction");

function TransformAction(entityView) {
	TransformAction._super.call(this, "transform", "Transform", entityView, EDIT_BASE_PATH
			+ EDIT_TRANSFORM_URL);
}
Object.extend("TransformAction", "EditAction");

function UndoAction(entityView) {
	UndoAction._super.call(this, "undo", "Undo", entityView, EDIT_BASE_PATH + EDIT_HISTORY_URL);
}
Object.extend("UndoAction", "EditAction");

function ClipboardAction(id, label, entityView) {
	var uri = ClipboardAction.jobUri;
	if (!uri)
		uri = EDIT_BASE_PATH + EDIT_CLIPBOARD_JOB_URL;
	ClipboardAction._super.call(this, id, label, entityView, uri);
}
Object.extend("ClipboardAction", "EditAction");

function CutAction(entityView) {
	CutAction._super.call(this, "cut", "Cut", entityView);
}
Object.extend("CutAction", "ClipboardAction");

CutAction.prototype.prepareReselect = function() {
	var sel = this.entityView.getNextSibling();
	if (!sel)
		sel = this.entityView.getPreviousSibling();
	if (sel && this.entityView.id.match("\\.[0-9]*$"))
		sel = this.entityView;
	if (!sel)
		sel = this.entityView.getParent();
	return (sel)?sel.dom.element.id:null;
}

function CopyAction(entityView) {
	CopyAction._super.call(this, "copy", "Copy", entityView);
}
Object.extend("CopyAction", "ClipboardAction");

function PasteAction(entityView) {
	PasteAction._super.call(this, "paste", "Paste", entityView);
}
Object.extend("PasteAction", "ClipboardAction");

PasteAction.prototype.reselect = function(ev, responseDom) {
	if (responseDom) {
		var ins = responseDom.getElementsByTagName("insert")[0];
		if (ins) {
			var id = ins.getAttribute("ref");
			var objId = ins.parentNode.parentNode.getAttribute("obj");
			var evNew = EntityView.getFirstEntityViewById(null, objId, id);
			if (evNew)
				ev = evNew;
		}
	}
	this.doc.selectionSupport.select(ev);
}

function PasteIntoAction(entityView, path) {
	PasteIntoAction._super.call(this, "pasteInto", "Paste Into", entityView);
	this.path = path;
}
Object.extend("PasteIntoAction", "ClipboardAction");

PasteIntoAction.prototype.addData = function(editJob) {
	editJob.addEntityIdData(this.entityView.entity);
	if (this.path) {
		editJob.addData("path", this.path);
		for (var i = 0; i < this.namespaces.length; ++i) {
			var ns = this.namespaces[i];
			editJob.addData("ns-" + ns.getAttribute("prefix"), ns.getAttribute("uri"));
		}
	}
}

PasteIntoAction.prototype.reselect = function(ev, responseDom) {
	ev = ev.getLastChild();
	if (responseDom) {
		var ins = responseDom.getElementsByTagName("insert")[0];
		if (ins) {
			var id = ins.getAttribute("ref");
			var objId = ins.parentNode.parentNode.getAttribute("obj");
			var evNew = EntityView.getFirstEntityViewById(null, objId, id);
			if (evNew)
				ev = evNew;
		}
	}
	this.doc.selectionSupport.select(ev);
}
